// File Name: epwm_v1_cpu01.c
// Notes:
// 1. 3-phase non-interleaved Boost + Output Inverter
//
// 2. 3-phase non-interleaved Boost:
//    A:Q1-Q2, B:Q1-Q2, C:Q1-Q2
//    Output Inverter:
//    A:Q3-Q4, B:Q3-Q4, C:Q3-Q4
//
// PWM1A = A:Q1, PWM1B = A:Q2, PWM2A = A:Q3, PWM2B = A:Q4
// PWM3A = B:Q1, PWM3B = B:Q2, PWM4A = B:Q3, PWM4B = B:Q4
// PWM5A = C:Q1, PWM5B = C:Q2, PWM6A = C:Q3, PWM6B = C:Q4


//
//
//
//


//
// Included Files
//
#include "F28x_Project.h"
#include <math.h>
//
// Defines
//
#define SYSCLK_FREQ     (200000000)     // 200 MHz, system clock frequency
#define PWMCLK_FREQ     (100000000)     // 100 MHz, PWM clock frequency
#define FSW             (50000.0)       // 50 kHz, switching frequency
#define F0              (25.0)          // fundamental frequency
#define THETA_CNT_MAX   (FSW/F0)        // maximum index for theta[k] in a fumdamental cycle

#define EPWM_PERIOD (PWMCLK_FREQ / FSW / 2)
#define PHASE_SHIFT (1)

#define MI_MAX (0.99)
#define MI_MIN (0.01)

#define EPWM1_MAX_DB   0x03FF
#define EPWM2_MAX_DB   0x03FF
#define EPWM3_MAX_DB   0x03FF
#define EPWM1_MIN_DB   30 // 25 => 0.25 us, 50 => 0.5 us
#define EPWM2_MIN_DB   30
#define EPWM3_MIN_DB   0
#define DB_UP          1
#define DB_DOWN        0

#define TWO_PI          (6.283185307179586476925286766559)
#define TWO_PI_DIV_3    (2.0943951023931954923084289221863)
#define SQRT3          (1.7320508075688772935274463415059)
#define SQRT3_DIV_2    (0.86602540378443864676372317075294)

#define MAX_TWO(x,y)    ( ( (x) > (y) ) ? (x) : (y) )
#define MIN_TWO(x,y)    ( ( (x) < (y) ) ? (x) : (y) )

float periodd=0.5;
float DutyBoost;
float DutyBuck;
float DutyBoostA;
float DutyBoostB;
float DutyBoostC;
float DutyBuckA;
float DutyBuckB;
float DutyBuckC;
float ModSigA;
float ModSigB;
float ModSigC;
float ThetaA;
float ThetaB;
float ThetaC;

float temp1;
float maxCosine;
float minCosine;
float Vref_A_pu;
float Vref_B_pu;
float Vref_C_pu;
float Vin_pu;
float Vpk_Gain;

Uint16 theta_cnt;
Uint16 Pwm1CmpVal;
Uint16 Pwm2CmpVal;
Uint16 Pwm3CmpVal;
Uint16 Pwm4CmpVal;
Uint16 Pwm5CmpVal;
Uint16 Pwm6CmpVal;
Uint16 cycles_cnt;
Uint16 cycles_max;
Uint16 start_test;
float theta;
float MI;
float D0;
float softstart_inc;
float duty_inc;

#define ADC_CUR_SCALE_FACTOR (0.0174428745857) // (1.0/4095*3.0/0.042) , CurAmp * Volt/Amp * 4095/3.0 = ADC_RESULT_VALUE        1 A * (1.860-1.030)V/20A * 4096 / 3.0, 42 mV/A
#define ADC_VOL_SCALE_FACTOR (1.0) // Volts * Volt/Volt * 4095/3.0 = ADC_RESULT_VALUE
float ac_cur_senseOffset;
float Aix1;
float Aix2;
float Avdc;
float Bix1;
float Bix2;
float Bvdc;
float Cix1;
float Cix2;
float Cvdc;
float OCP;
float OVP;

//#define BUFFER_SIZE (512)
//Uint16 save;
//Uint16 index;
//Uint16 view[BUFFER_SIZE];

#define RESULTS_BUFFER_SIZE 100
int16 AdcaResult1[RESULTS_BUFFER_SIZE];
int16 AdcaResult2[RESULTS_BUFFER_SIZE];
int16 AdcaResult3[RESULTS_BUFFER_SIZE];
Uint16 resultsIndex;
volatile Uint16 bufferFull;

void InitEPwm1Example(void);
void InitEPwm2Example(void);
void InitEPwm3Example(void);
void InitEPwm4Example(void);
void InitEPwm5Example(void);
void InitEPwm6Example(void);

__interrupt void epwm1_isr(void);

void ConfigureADC(void);
void SetupADCEpwm(Uint16 channel);
interrupt void adca1_isr(void);  //interrupt void adcb_isr(void);
//interrupt void adca2_isr(void);  //interrupt void adcb_isr(void);
//interrupt void adca4_isr(void);  //interrupt void adcb_isr(void);
void all_pwm_off(void);

//
// Main
//
void main(void)
{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
    InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to its default state.
//
//    InitGpio();

    EALLOW;

    GpioCtrlRegs.GPAPUD.bit.GPIO14 = 1;    // Disable pull-up
    GpioCtrlRegs.GPAPUD.bit.GPIO15 = 1;    // Disable pull-up

    GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0;
    GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 0;

    GpioCtrlRegs.GPADIR.bit.GPIO14 = 1;
    GpioCtrlRegs.GPADIR.bit.GPIO15 = 1;

    EDIS;

//
// enable PWM1, PWM2 and PWM3
//
    CpuSysRegs.PCLKCR2.bit.EPWM1=1;
    CpuSysRegs.PCLKCR2.bit.EPWM2=1;
    CpuSysRegs.PCLKCR2.bit.EPWM3=1;
    CpuSysRegs.PCLKCR2.bit.EPWM4=1;
    CpuSysRegs.PCLKCR2.bit.EPWM5=1;
    CpuSysRegs.PCLKCR2.bit.EPWM6=1;

//
// For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
// These functions are in the F2837xD_EPwm.c file
//

    InitEPwm1Gpio();
    InitEPwm2Gpio();
    InitEPwm3Gpio();
    InitEPwm4Gpio();
    InitEPwm5Gpio();
    InitEPwm6Gpio();
//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
    DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
    InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
    IER = 0x0000;
    IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
    InitPieVectTable();

//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.EPWM1_INT = &epwm1_isr;
    // PieVectTable.EPWM2_INT = &epwm2_isr;
    // PieVectTable.EPWM3_INT = &epwm3_isr;
//    PieVectTable.ADCA1_INT = &adca1_isr; //function for ADCA interrupt 1
//    PieVectTable.ADCB2_INT = &adca2_isr; //function for ADCB interrupt 2
    PieVectTable.ADCC4_INT = &adca1_isr; //function for ADCC interrupt 4
    EDIS;   // This is needed to disable write to EALLOW protected registers

//
// Configure the ADC and power it up
//
    ConfigureADC();
//
// Step 4. Initialize the Device Peripherals:
//
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0;
    EDIS;

    InitEPwm1Example();
    InitEPwm2Example();
    InitEPwm3Example();
    InitEPwm4Example();
    InitEPwm5Example();
    InitEPwm6Example();

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =1;
    EDIS;


//
// Setup the ADC for ePWM triggered conversions on channel 0
//
    SetupADCEpwm(0);

//
// Step 5. User specific code, enable interrupts:
// Initialize counters:
//

    theta_cnt = 0;
    theta = 0.0;
    D0 = 0.5;

    Pwm1CmpVal = 0;
    Pwm2CmpVal = 0;
    Pwm3CmpVal = 0;
    Pwm4CmpVal = 0;
    Pwm5CmpVal = 0;
    Pwm6CmpVal = 0;

    cycles_cnt = 0;
    cycles_max = 1;
    start_test = 0;

    OCP = 50.0; // Over current protection 50 A

    ac_cur_senseOffset = 32.3;

    DutyBoost = 1.0;
    DutyBuck = 0.0;

    MI = 0.05;
    // MI = MI_MAX;
    softstart_inc = (0.99 - 0.05) / 50000.0 * 5.0; // 1/5 s

    temp1 = 0.0;
    maxCosine = 0.0;
    minCosine = 0.0;
    Vref_A_pu = 0.0;
    Vref_B_pu = 0.0;
    Vref_C_pu = 0.0;

    // Vout_LL_max_pu = sqrt(3)/2 = 0.866
    // If Vout_LL_max = 600 V, Vin = 200 V
    // Then Vin_pu = sqrt(3)/2 * Vin / Vout_LL_max = 0.866 * 200/600 = 0.28867
    Vpk_Gain = 3.0;
    Vin_pu = SQRT3_DIV_2 / Vpk_Gain;

    //
    // Initialize results buffer
    //
    for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
    {
        AdcaResult1[resultsIndex] = 0;
        AdcaResult2[resultsIndex] = 0;
        AdcaResult3[resultsIndex] = 0;
    }
    resultsIndex = 0;
    bufferFull = 0;


//
// Enable CPU INT3 which is connected to EPWM1-3 INT:
//
    IER |= M_INT1; //Enable group 1 interrupts
    IER |= M_INT10;

//
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
//
    // PieCtrlRegs.PIEIER1.bit.INTx1 = 1;
    // PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
    // PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
    // PieCtrlRegs.PIEIER10.bit.INTx6 = 1;
    PieCtrlRegs.PIEIER10.bit.INTx12 = 1;

//
// Enable global Interrupts and higher priority real-time debug events:
//
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

//
// Step 6. IDLE loop. Just sit and loop forever (optional):
//
    for(;;)
    {
        asm ("          NOP");
    }
}


//
// epwm1_isr - EPWM1 ISR
//
__interrupt void epwm1_isr(void)
{

    //
    // Clear INT flag for this timer
    //
    EPwm1Regs.ETCLR.bit.INT = 1;

    //
    // Acknowledge this interrupt to receive more interrupts from group 3
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}


//
// InitEPwm1Example - Initialize EPWM1 configuration
//
void InitEPwm1Example()
{

    EPwm1Regs.TBPRD = EPWM_PERIOD;                       // Set timer period
    //EPwm1Regs.TBCTL.bit.PHSEN = 0;

   // EPwm1Regs.TBCTL.bit.SWFSYNC=1;  //Writing a 1 forces a one-time synchronization pulse to begenerated.
    EPwm1Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;           // Phase is 0
    EPwm1Regs.TBCTR = 0x0000;                     // Clear counter
    //EPwm1Regs.HRPCTL.bit.PWMSYNCSEL=1;
    //
    // Setup TBCLK
    //
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
   // EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;    // Load registers every ZERO
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //
    // Setup compare
    //
    EPwm1Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm1Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm1Regs.AQCTLA.bit.CAD = AQ_SET;

    EPwm1Regs.AQCTLB.bit.CAU = AQ_SET;
    EPwm1Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    //  Setup Deadband
    //
    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm1Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm1Regs.DBRED.bit.DBRED = EPWM1_MIN_DB;
    EPwm1Regs.DBFED.bit.DBFED = EPWM1_MIN_DB;

    EPwm1Regs.ETSEL.bit.SOCASEL = 1;   // Select SOC on zero
    EPwm1Regs.ETPS.bit.SOCAPRD  = 1;       // Generate pulse on 1st event
    EPwm1Regs.ETSEL.bit.SOCAEN  = 1;

    //
    // Interrupt where we will change the Deadband
    //
    EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;    // Select INT on Zero event
    EPwm1Regs.ETSEL.bit.INTEN = 0;               // Enable INT
    EPwm1Regs.ETPS.bit.INTPRD = ET_1ST;          // Generate INT on 3rd event
}

//
// InitEPwm2Example - Initialize EPWM2 configuration
//
void InitEPwm2Example()
{
    EPwm2Regs.TBPRD = EPWM_PERIOD;                       // Set timer period


    EPwm2Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm2Regs.TBCTL.bit.PHSEN=1;
    EPwm2Regs.TBPHS.bit.TBPHS = 0;           // Phase


    EPwm2Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
 //   EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Slow just to observe on
                                                   // the scope

    //
    // Setup compare
    //
    EPwm2Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm2Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;            // Set PWM2A on Zero
    EPwm2Regs.AQCTLA.bit.CAD = AQ_SET;

    EPwm2Regs.AQCTLB.bit.CAU = AQ_SET;          // Set PWM2A on Zero
    EPwm2Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    // Active Low complementary PWMs - setup the deadband
    //
    EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm2Regs.DBRED.bit.DBRED = EPWM2_MIN_DB;
    EPwm2Regs.DBFED.bit.DBFED = EPWM2_MIN_DB;


    //
    // Interrupt where we will modify the deadband
    //
//    EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
//    EPwm2Regs.ETSEL.bit.INTEN = 1;                // Enable INT
//    EPwm2Regs.ETPS.bit.INTPRD = ET_DISABLE;           // Generate INT on 3rd event
}

//
// InitEPwm3Example - Initialize EPWM3 configuration
//
void InitEPwm3Example()
{
    EPwm3Regs.TBPRD = EPWM_PERIOD;                       // Set timer period

#if PHASE_SHIFT
    EPwm3Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm3Regs.TBCTL.bit.PHSEN = 1;
    EPwm3Regs.TBCTL.bit.PHSDIR = 1;
    EPwm3Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*2;           // Phase
#else
    EPwm3Regs.TBCTL.bit.PHSEN=0;
    EPwm3Regs.TBPHS.bit.TBPHS = 0;           // Phase
#endif

    EPwm3Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
   // EPwm3Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm3Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm3Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Slow just to observe on
                                                   // the scope

    //
    // Setup compare
    //
    EPwm3Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm3Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm3Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm3Regs.AQCTLA.bit.CAD = AQ_SET;
    EPwm3Regs.AQCTLB.bit.CAU = AQ_SET;
    EPwm3Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    // Active Low complementary PWMs - setup the deadband
    //
    EPwm3Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm3Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm3Regs.DBRED.bit.DBRED = EPWM2_MIN_DB;
    EPwm3Regs.DBFED.bit.DBFED = EPWM2_MIN_DB;


    //
    // Interrupt where we will modify the deadband
    //
//    EPwm3Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
//    EPwm3Regs.ETSEL.bit.INTEN = 1;                // Enable INT
//    EPwm3Regs.ETPS.bit.INTPRD = ET_DISABLE;           // Generate INT on 3rd event
}


void InitEPwm4Example()
{
    EPwm4Regs.TBPRD = EPWM_PERIOD;                       // Set timer period
    EPwm4Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm4Regs.TBCTL.bit.PHSEN=1;
//    EPwm4Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*2;           // Phase
    EPwm4Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*2*0;
    EPwm4Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
   // EPwm4Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm4Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm4Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Slow just to observe on
                                                   // the scope

    //
    // Setup compare
    //
    EPwm4Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm4Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm4Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm4Regs.AQCTLA.bit.CAD = AQ_SET;
    EPwm4Regs.AQCTLB.bit.CAU = AQ_SET;
    EPwm4Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    // Active Low complementary PWMs - setup the deadband
    //
    EPwm4Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm4Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm4Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm4Regs.DBRED.bit.DBRED = EPWM2_MIN_DB;
    EPwm4Regs.DBFED.bit.DBFED = EPWM2_MIN_DB;


    //
    // Interrupt where we will modify the deadband
    //
//    EPwm4Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
//    EPwm4Regs.ETSEL.bit.INTEN = 1;                // Enable INT
//    EPwm4Regs.ETPS.bit.INTPRD = ET_DISABLE;           // Generate INT on 3rd event
}

void InitEPwm5Example()
{
    EPwm5Regs.TBPRD = EPWM_PERIOD;                       // Set timer period

#if PHASE_SHIFT
    EPwm5Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm5Regs.TBCTL.bit.PHSEN = 1;
    EPwm5Regs.TBCTL.bit.PHSDIR = 0;
    EPwm5Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*2;           // Phase
#else
    EPwm5Regs.TBCTL.bit.PHSEN=0;
    EPwm5Regs.TBPHS.bit.TBPHS = 0;           // Phase
#endif


    EPwm5Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
    //EPwm5Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Slow just to observe on
                                                   // the scope

    //
    // Setup compare
    //
    EPwm5Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm5Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm5Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm5Regs.AQCTLA.bit.CAD = AQ_SET;
    EPwm5Regs.AQCTLB.bit.CAU = AQ_SET;
    EPwm5Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    // Active Low complementary PWMs - setup the deadband
    //
    EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm5Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm5Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm5Regs.DBRED.bit.DBRED = EPWM2_MIN_DB;
    EPwm5Regs.DBFED.bit.DBFED = EPWM2_MIN_DB;


    //
    // Interrupt where we will modify the deadband
    //
//    EPwm5Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
//    EPwm5Regs.ETSEL.bit.INTEN = 1;                // Enable INT
//    EPwm5Regs.ETPS.bit.INTPRD = ET_DISABLE;           // Generate INT on 3rd event
}

void InitEPwm6Example()
{
    EPwm6Regs.TBPRD = EPWM_PERIOD;                       // Set timer period
//    EPwm6Regs.TBCTL.bit.SYNCOSEL=1;
    EPwm6Regs.TBCTL.bit.PHSEN=1;
//    EPwm6Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*4;           // Phase
 //   EPwm6Regs.TBPHS.bit.TBPHS = EPWM_PERIOD/3*4*0;           // Phase
    EPwm6Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count up
    //EPwm6Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;       // Clock ratio to SYSCLKOUT
    EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;          // Slow just to observe on
                                                   // the scope

    //
    // Setup compare
    //
    EPwm6Regs.CMPA.bit.CMPA = 0.5 * EPWM_PERIOD;
//    EPwm6Regs.CMPB.bit.CMPB = 250;

    //
    // Set actions
    //
    EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm6Regs.AQCTLA.bit.CAD = AQ_SET;
    EPwm6Regs.AQCTLB.bit.CAU = AQ_SET;
    EPwm6Regs.AQCTLB.bit.CAD = AQ_CLEAR;

    //
    // Active Low complementary PWMs - setup the deadband
    //
    EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm6Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm6Regs.DBRED.bit.DBRED = EPWM2_MIN_DB;
    EPwm6Regs.DBFED.bit.DBFED = EPWM2_MIN_DB;


    //
    // Interrupt where we will modify the deadband
    //
//    EPwm6Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
//    EPwm6Regs.ETSEL.bit.INTEN = 1;                // Enable INT
//    EPwm6Regs.ETPS.bit.INTPRD = ET_DISABLE;           // Generate INT on 3rd event
}

//
// ConfigureADC - Write ADC configurations and power up the ADC for both
//                ADC A and ADC B
//
void ConfigureADC(void)
{
    EALLOW;

    //
    //write configurations
    //
    AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
    AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
   // AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0;           //Single-ended

    //
    //Set pulse positions to late
    //
    AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 6;
    //
    //power up the ADC
    //
    AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    //
    //delay for 1ms to allow ADC time to power up
    //
    DELAY_US(1000);


    AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
    AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
    //
    //Set pulse positions to late
    //
    AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;
    //
    //power up the ADC
    //
    AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    //
    //delay for 1ms to allow ADC time to power up
    //
    DELAY_US(1000);

    AdccRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
    AdcSetMode(ADC_ADCC, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);
    //
    //Set pulse positions to late
    //
    AdccRegs.ADCCTL1.bit.INTPULSEPOS = 1;
    //
    //power up the ADC
    //
    AdccRegs.ADCCTL1.bit.ADCPWDNZ = 1;
    //
    //delay for 1ms to allow ADC time to power up
    //
    DELAY_US(1000);

    EDIS;
}

//
// SetupADCEpwm - Setup ADC EPWM acquisition window
//
void SetupADCEpwm(Uint16 channel)
{
    Uint16 acqps;

    //
    //determine minimum acquisition window (in SYSCLKS) based on resolution
    //
    if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
    {
        acqps = 14; //75ns
    }
    else //resolution is 16-bit
    {
        acqps = 63; //320ns
    }

    //
    //Select the channels to convert and end of conversion flag
    //
    // A0: A:IX1
    // A1: A:IX2
    // A3: A:VDC
    // B2: B:IX1
    // B3: B:IX2
    // B4: B:VDC
    // C2: C:IX1
    // C3: C:IX2
    // C4: C:VDC

    EALLOW;
    AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel;  //SOC0 will convert pin A0
    AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
    AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA

    AdcaRegs.ADCSOC1CTL.bit.CHSEL = 1;//SOC1 will convert pin A1
    AdcaRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 5;

    AdcaRegs.ADCSOC2CTL.bit.CHSEL = 3;//SOC2 will convert pin A2
    AdcaRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    AdcaRegs.ADCSOC2CTL.bit.TRIGSEL = 5;


    AdcbRegs.ADCSOC0CTL.bit.CHSEL = 2;  //SOC3 will convert pin B2
    AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
    AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA

    AdcbRegs.ADCSOC1CTL.bit.CHSEL = 3;//SOC4 will convert pin B3
    AdcbRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    AdcbRegs.ADCSOC1CTL.bit.TRIGSEL = 5;

    AdcbRegs.ADCSOC2CTL.bit.CHSEL = 4;//SOC5 will convert pin B4
    AdcbRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    AdcbRegs.ADCSOC2CTL.bit.TRIGSEL = 5;

    AdccRegs.ADCSOC0CTL.bit.CHSEL = 2;  //SOC6 will convert pin C2
    AdccRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
    AdccRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA

    AdccRegs.ADCSOC1CTL.bit.CHSEL = 3;//SOC7 will convert pin C3
    AdccRegs.ADCSOC1CTL.bit.ACQPS = acqps;
    AdccRegs.ADCSOC1CTL.bit.TRIGSEL = 5;

    AdccRegs.ADCSOC2CTL.bit.CHSEL = 4;//SOC8 will convert pin C4
    AdccRegs.ADCSOC2CTL.bit.ACQPS = acqps;
    AdccRegs.ADCSOC2CTL.bit.TRIGSEL = 5;

    AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 2; //end of SOC8 will set INT1 flag
    AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1;   //enable INT1 flag
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared

    AdcbRegs.ADCINTSEL1N2.bit.INT2SEL = 2; //end of SOC2 will set INT1 flag
    AdcbRegs.ADCINTSEL1N2.bit.INT2E = 1;   //enable INT1 flag
    AdcbRegs.ADCINTFLGCLR.bit.ADCINT2 = 1; //make sure INT1 flag is cleared

    AdccRegs.ADCINTSEL3N4.bit.INT4SEL = 2; //end of SOC8 will set INT4 flag
    AdccRegs.ADCINTSEL3N4.bit.INT4E = 1;   //enable INT4 flag
    AdccRegs.ADCINTFLGCLR.bit.ADCINT4 = 1; //make sure INT4 flag is cleared

    EDIS;
}


//
// adca1_isr - Read ADC Buffer in ISR
//

interrupt void adca1_isr(void)
{
    GpioDataRegs.GPASET.bit.GPIO14 = 1;

    Aix1 = (((float) AdcaResultRegs.ADCRESULT0) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Aix2 = (((float) AdcaResultRegs.ADCRESULT1) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Avdc = (((float) AdcaResultRegs.ADCRESULT2) * ADC_VOL_SCALE_FACTOR);

    Bix1 = (((float) AdcbResultRegs.ADCRESULT3) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Bix2 = (((float) AdcbResultRegs.ADCRESULT4) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Bvdc = (((float) AdcbResultRegs.ADCRESULT5) * ADC_VOL_SCALE_FACTOR);

    Cix1 = (((float) AdccResultRegs.ADCRESULT6) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Cix2 = (((float) AdccResultRegs.ADCRESULT7) * ADC_CUR_SCALE_FACTOR - ac_cur_senseOffset);
    Cvdc = (((float) AdccResultRegs.ADCRESULT8) * ADC_VOL_SCALE_FACTOR);


    if( (OCP < Aix1) || (OCP < Aix2) || (OCP < Bix1) || (OCP < Bix2) || (OCP < Cix1) || (OCP < Cix2))
    {
        all_pwm_off();
    }


    if(start_test)
    {
        theta_cnt++;
        if(theta_cnt > THETA_CNT_MAX)
        {
            theta_cnt = 0;
        }
        theta = TWO_PI * theta_cnt / THETA_CNT_MAX;

        ThetaA = theta;
        ThetaB = theta - TWO_PI_DIV_3;
        ThetaC = theta + TWO_PI_DIV_3;

        if(ThetaB < 0) {ThetaB = ThetaB + TWO_PI;}
        if(ThetaC >= TWO_PI) {ThetaC = ThetaC - TWO_PI;}

        if(theta_cnt == 0)
        {
            cycles_cnt++;
        }

        if(cycles_cnt > cycles_max)
        {
            cycles_cnt = 0;
            start_test = 0;
        }
        else
        {
            MI = MI + softstart_inc;
            if(MI >= MI_MAX)
            {
                MI = MI_MAX;
            }

            ModSigA = 0.5 + MI * 0.5 * cos(ThetaA);
            ModSigB = 0.5 + MI * 0.5 * cos(ThetaB);
            ModSigC = 0.5 + MI * 0.5 * cos(ThetaC);

            temp1 = MAX_TWO(ModSigA, ModSigB);
            maxCosine = MAX_TWO(temp1, ModSigC);

            temp1 = MIN_TWO(ModSigA, ModSigB);
            minCosine = MIN_TWO(temp1, ModSigC);

            Vref_A_pu = ModSigA - minCosine;
            Vref_B_pu = ModSigB - minCosine;
            Vref_C_pu = ModSigC - minCosine;


            Vin_pu = SQRT3_DIV_2 / Vpk_Gain;

            // Boost-Buck Inverter
            DutyBoostA = ( Vref_A_pu > Vin_pu ) ? (Vin_pu / Vref_A_pu) : (1.0);
            DutyBoostB = ( Vref_B_pu > Vin_pu ) ? (Vin_pu / Vref_B_pu) : (1.0);
            DutyBoostC = ( Vref_C_pu > Vin_pu ) ? (Vin_pu / Vref_C_pu) : (1.0);

            DutyBuckA = ( Vref_A_pu < Vin_pu ) ? (Vref_A_pu / Vin_pu) : (1.0);
            DutyBuckB = ( Vref_B_pu < Vin_pu ) ? (Vref_B_pu / Vin_pu) : (1.0);
            DutyBuckC = ( Vref_C_pu < Vin_pu ) ? (Vref_C_pu / Vin_pu) : (1.0);

            // for Boost Inverter test only
            // DutyBoost = 0.3333, 200V => 600V, Vph_pk = 300, Vll_pk = 520
            // DutyBoost = 0.2887, 200V => 692V, Vph_pk = 346, Vll_pk = 600

//            duty_inc = (Vin_pu - 0.99) * 0.0001;
//
//            DutyBoost = DutyBoost + duty_inc;
//            if(DutyBoost <= Vin_pu)
//            {
//                DutyBoost = Vin_pu;
//            }

//            DutyBoostA = DutyBoost;
//            DutyBoostB = DutyBoost;
//            DutyBoostC = DutyBoost;
//            DutyBuckA = ModSigA;
//            DutyBuckB = ModSigB;
//            DutyBuckC = ModSigC;
//            DutyBuckA = Vref_A_pu;
//            DutyBuckB = Vref_B_pu;
//            DutyBuckC = Vref_C_pu;

            // for single-phase inverter test only
//            DutyBoostA = ModSigA;
//            DutyBoostB = ModSigA;
//            DutyBoostC = ModSigA;
//            DutyBuckA = 1.0 - ModSigA;
//            DutyBuckB = 1.0 - ModSigA;
//            DutyBuckC = 1.0 - ModSigA;
        }
    }
    else
    {
        DutyBoostA = 1.0; // can not be 0, would short dc source
        DutyBoostB = 1.0; // can not be 0, would short dc source
        DutyBoostC = 1.0; // can not be 0, would short dc source

        // DutyBuck = 1.0;

        DutyBuckA = DutyBuck;
        DutyBuckB = DutyBuck;
        DutyBuckC = DutyBuck;

        MI = 0.05;
    }

//    DutyBoostA = D0;
//    DutyBoostB = D0;
//    DutyBoostC = D0;
//    DutyBuckA = D0;
//    DutyBuckB = D0;
//    DutyBuckC = D0;

    Pwm1CmpVal = DutyBoostA * EPWM_PERIOD;
    Pwm3CmpVal = DutyBoostB * EPWM_PERIOD;
    Pwm5CmpVal = DutyBoostC * EPWM_PERIOD;

    Pwm2CmpVal = DutyBuckA * EPWM_PERIOD;
    Pwm4CmpVal = DutyBuckB * EPWM_PERIOD;
    Pwm6CmpVal = DutyBuckC * EPWM_PERIOD;

//    duty = 0.5 + MI * 0.5 * cos(theta);
//    duty = D0;

    if(start_test)
    {
         GpioDataRegs.GPASET.bit.GPIO15 = 1;

         AdcaResult1[resultsIndex] = DutyBoostA * 1000;
         AdcaResult2[resultsIndex] = DutyBoostB * 1000;
         AdcaResult3[resultsIndex] = DutyBuckA * 1000;

        resultsIndex++;
        if(RESULTS_BUFFER_SIZE <= resultsIndex)
        {
            resultsIndex = 0;
            bufferFull = 1;
        }
    }
    else
    {
         GpioDataRegs.GPACLEAR.bit.GPIO15 = 1;
    }

    EPwm1Regs.CMPA.bit.CMPA = Pwm1CmpVal;
    EPwm2Regs.CMPA.bit.CMPA = Pwm2CmpVal;

    EPwm3Regs.CMPA.bit.CMPA = Pwm3CmpVal;
    EPwm4Regs.CMPA.bit.CMPA = Pwm4CmpVal;

    EPwm5Regs.CMPA.bit.CMPA = Pwm5CmpVal;
    EPwm6Regs.CMPA.bit.CMPA = Pwm6CmpVal;


    GpioDataRegs.GPACLEAR.bit.GPIO14 = 1;

//    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT4 flag
//    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

    AdccRegs.ADCINTFLGCLR.bit.ADCINT4 = 1; //clear INT4 flag
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP10;
}

void all_pwm_off(void)
{
    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
    EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
    EPwm3Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
    EPwm4Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
    EPwm5Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HI;

    EPwm1Regs.AQCSFRC.bit.CSFA = 1; //0101: Forces a continuous low on output A and B
    EPwm1Regs.AQCSFRC.bit.CSFB = 1;
    EPwm2Regs.AQCSFRC.bit.CSFA = 1;
    EPwm2Regs.AQCSFRC.bit.CSFB = 1;
    EPwm3Regs.AQCSFRC.bit.CSFA = 1;
    EPwm3Regs.AQCSFRC.bit.CSFB = 1;
    EPwm4Regs.AQCSFRC.bit.CSFA = 1;
    EPwm4Regs.AQCSFRC.bit.CSFB = 1;
    EPwm5Regs.AQCSFRC.bit.CSFA = 1;
    EPwm5Regs.AQCSFRC.bit.CSFB = 1;
    EPwm6Regs.AQCSFRC.bit.CSFA = 1;
    EPwm6Regs.AQCSFRC.bit.CSFB = 1;

    //
    // disable PWM
    //
    CpuSysRegs.PCLKCR2.bit.EPWM1 = 0;
    CpuSysRegs.PCLKCR2.bit.EPWM2 = 0;
    CpuSysRegs.PCLKCR2.bit.EPWM3 = 0;
    CpuSysRegs.PCLKCR2.bit.EPWM4 = 0;
    CpuSysRegs.PCLKCR2.bit.EPWM5 = 0;
    CpuSysRegs.PCLKCR2.bit.EPWM6 = 0;
}

//
// End of file
//
